﻿using System.Collections.Generic;
using FireStarter.Base;
using FireStarterModeller.BO;
using FireStarterModeller.Logic;
using Habanero.Base;
using Habanero.BO.ClassDefinition;
using NUnit.Framework;

namespace FireStarterModeller.Test.Logic
{
    [TestFixture]
    public class TestDMToClassDefConverter_UIView
    {
        [TestFixtureSetUp]
        public void SetupFixture()
        {
            TestUtilsLogic.SetupFixture();
        }

        [SetUp]
        public void SetupTest()
        {
            TestUtilsLogic.SetupTest();
        }

        [Test]
        public void Test_UIViewConversion()
        {
            //---------------Set up test pack-------------------  
            DMClass dmClass = TestUtilsLogic.CreateClassWithOneGuidProperty();
            UIView view = AddViewToClass(dmClass);

            //---------------Execute Test ----------------------
            IUIDef uiDef = new DmToClassDefsConverter().Convert(view);

            //---------------Test Result -----------------------
            Assert.AreEqual(view.ViewName, uiDef.Name);
        }


        [Test]
        public void Test_UIGridInfoConversion()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = TestUtilsLogic.CreateClassWithOneGuidProperty();
            DMProperty property = dmClass.Properties[0];
            UIView view = AddViewToClass(dmClass);
            AddGridInfoToView(view, property);

            //---------------Execute Test ----------------------
            IUIDef uiDef = new DmToClassDefsConverter().Convert(view);

            //---------------Test Result -----------------------
            Assert.IsNotNull(uiDef.UIGrid);
            Assert.AreEqual(property.PropertyName, uiDef.UIGrid.SortColumn);
        }


        [Test]
        public void Test_UIGridInfoConversion_WithFilter()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = TestUtilsLogic.CreateClassWithOneGuidProperty();
            DMProperty property = dmClass.Properties[0];
            UIView view = AddViewToClass(dmClass);
            UIGridInfo gridInfo = AddGridInfoToView(view, property);
            UIGridFilter uiGridFilter = new UIGridFilter { FilterMode = FilterModes.Filter };
            UIGridFilterProp gridFilterProp = new UIGridFilterProp { PropertyName = property.PropertyName, FilterClauseOp = FilterClauseOperator.OpEquals };
            uiGridFilter.UIGridFilterProps.Add(gridFilterProp);
            gridInfo.UIGridFilter = uiGridFilter;
            //---------------Execute Test ----------------------
            IUIDef uiDef = new DmToClassDefsConverter().Convert(view);

            //---------------Test Result -----------------------
            IUIGrid grid = uiDef.UIGrid;
            Assert.IsNotNull(grid);
            Assert.AreEqual(property.PropertyName, grid.SortColumn);
            IFilterDef filterDef = grid.FilterDef;
            Assert.IsNotNull(filterDef);
            Assert.AreEqual(uiGridFilter.FilterMode, filterDef.FilterMode);
            Assert.AreEqual(1, filterDef.FilterPropertyDefs.Count);
        }

        [Test]
        public void Test_UIGridInfoConversion_WithFilter_WithParameters()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = TestUtilsLogic.CreateClassWithOneGuidProperty();
            DMProperty property = dmClass.Properties[0];
            UIView view = AddViewToClass(dmClass);
            UIGridInfo gridInfo = AddGridInfoToView(view, property);
            UIGridFilter uiGridFilter = new UIGridFilter { FilterMode = FilterModes.Filter };
            UIGridFilterProp gridFilterProp = new UIGridFilterProp { PropertyName = property.PropertyName };
            UIParameter uiParameter = new UIParameter
            {
                Name = TestUtilsShared.GetRandomString(),
                Value = TestUtilsShared.GetRandomString()
            };
            gridFilterProp.UIParameters.Add(uiParameter);
            uiGridFilter.UIGridFilterProps.Add(gridFilterProp);
            gridInfo.UIGridFilter = uiGridFilter;
            //---------------Execute Test ----------------------
            IUIDef uiDef = new DmToClassDefsConverter().Convert(view);

            //---------------Test Result -----------------------
            IUIGrid grid = uiDef.UIGrid;
            Assert.IsNotNull(grid);
            Assert.AreEqual(property.PropertyName, grid.SortColumn);
            IFilterDef filterDef = grid.FilterDef;
            Assert.IsNotNull(filterDef);
            Assert.AreEqual(uiGridFilter.FilterMode, filterDef.FilterMode);
            Assert.AreEqual(1, filterDef.FilterPropertyDefs.Count);
            IFilterPropertyDef filterPropertyDef = filterDef.FilterPropertyDefs[0];
            Assert.AreEqual(1, filterPropertyDef.Parameters.Count);
            Assert.IsTrue(filterPropertyDef.Parameters.ContainsKey(uiParameter.Name));
            Assert.AreEqual(uiParameter.Value, filterPropertyDef.Parameters[uiParameter.Name]);
        }

        [Test]
        public void Test_UIFilter_WithFilterProps()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = TestUtilsLogic.CreateClassWithOneGuidProperty();
            UIView view = AddViewToClass(dmClass);
            DMProperty property = dmClass.Properties[0];
            UIGridInfo gridInfo = AddGridInfoToView(view, property);
            UIGridFilter uiGridFilter = new UIGridFilter { FilterMode = FilterModes.Filter };
            UIGridFilterProp gridFilterProp = new UIGridFilterProp
            {
                PropertyName = property.PropertyName,
                LabelText = TestUtilsShared.GetRandomString(),
                ToolTipText = TestUtilsShared.GetRandomString()
            };
            UITypeDefinition typeDefinition = new UITypeDefinition
            {
                AssemblyName = TestUtilsShared.GetRandomString(),
                TypeName = TestUtilsShared.GetRandomString()
            };
            gridFilterProp.UIGridFilterType = typeDefinition;
            gridFilterProp.DefaultValue = TestUtilsShared.GetRandomString();
            gridFilterProp.FilterClauseOp = FilterClauseOperator.OpGreaterThan;
            uiGridFilter.UIGridFilterProps.Add(gridFilterProp);
            gridInfo.UIGridFilter = uiGridFilter;

            //---------------Execute Test ----------------------
            IUIDef uiDef = new DmToClassDefsConverter().Convert(view);
            IUIGrid grid = uiDef.UIGrid;

            //---------------Test Result -----------------------
            Assert.IsNotNull(grid);
            Assert.AreEqual(property.PropertyName, grid.SortColumn);
            IFilterDef filterDef = grid.FilterDef;
            Assert.IsNotNull(filterDef);
            Assert.AreEqual(uiGridFilter.FilterMode, filterDef.FilterMode);
            IList<IFilterPropertyDef> filterPropertyDefs = filterDef.FilterPropertyDefs;
            Assert.AreEqual(1, filterPropertyDefs.Count);
            IFilterPropertyDef filterPropertyDef = filterPropertyDefs[0];
            Assert.AreEqual(property.PropertyName, filterPropertyDef.PropertyName);
            Assert.AreEqual(gridFilterProp.LabelText, filterPropertyDef.Label);
            Assert.AreEqual(gridFilterProp.FilterClauseOp, filterPropertyDef.FilterClauseOperator);
            Assert.AreEqual(typeDefinition.AssemblyName, filterPropertyDef.FilterTypeAssembly);
            Assert.AreEqual(typeDefinition.TypeName, filterPropertyDef.FilterType);
        }

        [Test]
        public void Test_UIColumnInfoConversion()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = TestUtilsLogic.CreateClassWithOneGuidProperty();
            DMProperty property = dmClass.Properties[0];
            UIView view = AddViewToClass(dmClass);
            UIGridInfo gridInfo = new UIGridInfo();
            view.UIGridInfo = gridInfo;
            gridInfo.SortColumn = property.PropertyName;
            UIGridColumnInfo columnInfo = CreateUIGridColumnInfo(property);
            gridInfo.UIColumns.Add(columnInfo);
            //---------------Execute Test ----------------------
            IUIDef uiDef = new DmToClassDefsConverter().Convert(view);
            //---------------Test Result -----------------------
            Assert.IsNotNull(uiDef.UIGrid);
            IUIGridColumn uiGridColumn = uiDef.UIGrid[0];
            Assert.IsNotNull(uiGridColumn);
            Assert.AreEqual(property.PropertyName, uiGridColumn.PropertyName);
            Assert.AreEqual(columnInfo.Heading, uiGridColumn.Heading);
            //---------------Tear Down -------------------------          
        }

        [Test]
        public void Test_UIColumnInfoConversion_WithParamaters()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = TestUtilsLogic.CreateClassWithOneGuidProperty();
            DMProperty property = dmClass.Properties[0];
            UIView view = AddViewToClass(dmClass);
            UIGridInfo gridInfo = new UIGridInfo();
            view.UIGridInfo = gridInfo;
            gridInfo.SortColumn = property.PropertyName;
            UIGridColumnInfo columnInfo = CreateUIGridColumnInfo(property);
            UIParameter parameter = new UIParameter
            {
                Name = TestUtilsShared.GetRandomString(),
                Value = TestUtilsShared.GetRandomString()
            };
            columnInfo.UIParameters.Add(parameter);
            gridInfo.UIColumns.Add(columnInfo);
            //---------------Execute Test ----------------------
            IUIDef uiDef = new DmToClassDefsConverter().Convert(view);
            //---------------Test Result -----------------------
            Assert.IsNotNull(uiDef.UIGrid);
            IUIGridColumn uiGridColumn = uiDef.UIGrid[0];
            Assert.IsNotNull(uiGridColumn);
            Assert.AreEqual(property.PropertyName, uiGridColumn.PropertyName);
            Assert.AreEqual(columnInfo.Heading, uiGridColumn.Heading);
            Assert.AreEqual(1, uiGridColumn.Parameters.Count);
            object parameter1 = uiGridColumn.Parameters[parameter.Name];
            Assert.IsNotNull(parameter1);
            Assert.AreEqual(parameter.Value, parameter1.ToString());
            //---------------Tear Down -------------------------          
        }

        [Test]
        public void Test_UIColumnInfoConversion_WithAttributes()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = TestUtilsLogic.CreateClassWithOneGuidProperty();
            DMProperty property = dmClass.Properties[0];
            UIView view = AddViewToClass(dmClass);
            UIGridInfo gridInfo = new UIGridInfo();
            view.UIGridInfo = gridInfo;
            gridInfo.SortColumn = property.PropertyName;
            UIGridColumnInfo columnInfo = CreateUIGridColumnInfo(property);
            UIGridColumnControlType uiGridColumnControlType = new UIGridColumnControlType
            {
                AssemblyName = TestUtilsShared.GetRandomString(),
                TypeName = TestUtilsShared.GetRandomString()
            };
            columnInfo.UIGridColumnControlType = uiGridColumnControlType;
            columnInfo.Editable = false;
            columnInfo.Width = TestUtilsShared.GetRandomInt();
            columnInfo.Alignment = "right";
            gridInfo.UIColumns.Add(columnInfo);
            //----------Execute Test------------------------------
            IUIDef uiDef = new DmToClassDefsConverter().Convert(view);
            //---------------Test Result -----------------------
            Assert.IsNotNull(uiDef.UIGrid);
            IUIGridColumn uiGridColumn = uiDef.UIGrid[0];
            Assert.IsNotNull(uiGridColumn);
            Assert.AreEqual(property.PropertyName, uiGridColumn.PropertyName);
            Assert.AreEqual(columnInfo.Heading, uiGridColumn.Heading);
            Assert.IsFalse(uiGridColumn.Editable);
            Assert.AreEqual(columnInfo.Width, uiGridColumn.Width);
            Assert.AreEqual(uiGridColumnControlType.AssemblyName, uiGridColumn.GridControlAssemblyName);
            Assert.AreEqual(uiGridColumnControlType.TypeName, uiGridColumn.GridControlTypeName);
        }

        [Test]
        public void Test_UIFormConversion_DefaultAttributes()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = TestUtilsLogic.CreateClassWithOneGuidProperty();
            DMProperty property = dmClass.Properties[0];
            UIView view = AddViewToClass(dmClass);
            UIField formField = AddUIFormInfoToUIView(property, view);
            UIFormInfo formInfo = formField.UIColumnLayout.UITab.UIFormInfo;
            //---------------Execute Test ----------------------
            IUIDef uiDef = new DmToClassDefsConverter().Convert(view);
            //---------------Test Result -----------------------
            Assert.IsNotNull(uiDef);
            IUIForm uiForm = uiDef.UIForm;
            Assert.IsNotNull(uiForm);
            Assert.AreEqual(formInfo.Height, uiForm.Height);
            Assert.AreEqual(formInfo.Width, uiForm.Width);
            Assert.AreEqual(formInfo.Title, uiForm.Title);
        }

        [Test]
        public void Test_UIFormConversion_FormFieldHasParameters()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = TestUtilsLogic.CreateClassWithOneGuidProperty();
            DMProperty property = dmClass.Properties[0];
            UIView view = AddViewToClass(dmClass);
            UIField formField = AddUIFormInfoToUIView(property, view);
            UIParameter parameter = new UIParameter();
            parameter.Name = TestUtilsShared.GetRandomString();
            parameter.Value = TestUtilsShared.GetRandomString();
            formField.UIParameters.Add(parameter);
            //---------------Execute Test ----------------------
            IUIDef uiDef = new DmToClassDefsConverter().Convert(view);
            //---------------Test Result -----------------------
            Assert.IsNotNull(uiDef);
            IUIForm uiForm = uiDef.UIForm;
            Assert.IsNotNull(uiForm);
            IUIFormField uiFormField = uiForm[0][0][0];
            Assert.AreEqual(1, uiFormField.Parameters.Count);
            object parameter1 = uiFormField.Parameters[parameter.Name];
            Assert.IsNotNull(parameter1);
            Assert.AreEqual(parameter.Value, parameter1.ToString());
        }


        //TODO: Add layout to DM
        [Test]
        public void Test_UIFormConversion_WithTabs()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = TestUtilsLogic.CreateClassWithOneGuidProperty();
            DMProperty property = dmClass.Properties[0];
            UIView view = AddViewToClass(dmClass);
            UIField formField = AddUIFormInfoToUIView(property, view);

            //---------------Execute Test ----------------------
            IUIDef uiDef = new DmToClassDefsConverter().Convert(view);
            //---------------Test Result -----------------------
            Assert.IsNotNull(uiDef);
            IUIForm uiForm = uiDef.UIForm;
            Assert.IsNotNull(uiForm);
            IUIFormTab formTab = uiForm[0];
            Assert.IsNotNull(formTab);
            IUIFormColumn formColumn = formTab[0];
            Assert.IsNotNull(formColumn);
            IUIFormField uiFormField = formColumn[0];
            Assert.IsNotNull(uiFormField);
            Assert.AreEqual(formField.Editable, uiFormField.Editable);
            Assert.AreEqual(formField.ShowAsCompulsory, uiFormField.ShowAsCompulsory);
            Assert.AreEqual(formField.LabelText, uiFormField.GetLabel());
            Assert.AreEqual(formField.PropertyName, uiFormField.PropertyName);
            Assert.AreEqual(formField.ToolTipText, uiFormField.ToolTipText);
            Assert.AreEqual(formField.UIControlMapperType.AssemblyName, uiFormField.MapperAssembly);
            Assert.AreEqual(formField.UIControlMapperType.TypeName, uiFormField.MapperTypeName);
            Assert.AreEqual(formField.UIControlType.AssemblyName, uiFormField.ControlAssemblyName);
            Assert.AreEqual(formField.UIControlType.TypeName, uiFormField.ControlTypeName);
        }

        [Test]
        public void Test_UIFormConversion_RelationshipProps_UseRelationshipComboboxMapper()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = TestUtilsLogic.CreateClassWithOneGuidProperty();
            DMClass dmClass2 = TestUtilsLogic.CreateClassWithOneGuidProperty(dmClass.Assembly);
            DMProperty property = dmClass.Properties.CreateBusinessObject();

            property.PropertyName = TestUtilsShared.GetRandomString();
            property.PropertyType = TestUtilsLogic.GetGuidPropertyType();
            property.DefaultPropRule = null;
            DMRelationship relationship = dmClass.OwnerRelationships.CreateBusinessObject();
            relationship.RelationshipName = TestUtilsShared.GetRandomString();
            relationship.ReverseRelationship.RelationshipName = TestUtilsShared.GetRandomString();
            relationship.ReverseRelationship.ClassDM = dmClass2;
            DMRelationshipProperty relationshipProperty = relationship.RelationshipProperties.CreateBusinessObject();
            relationshipProperty.OwnerProperty = property;
            relationshipProperty.RelatedProperty = dmClass2.Properties[0];

            UIView view = dmClass.UIViews.CreateBusinessObject();
            view.UIFormInfo = new UIFormInfo();
            UITab uiTab = view.UIFormInfo.UITabs.CreateBusinessObject();

            UIColumnLayout columnLayout = uiTab.UIColumnLayouts.CreateBusinessObject();
            UIField formField = columnLayout.UIFields.CreateBusinessObject();
            formField.PropertyName = relationship.RelationshipName;
            UIControlMapperType uiControlMapperType = new UIControlMapperType
            {
                AssemblyName = BOBroker.GetMapperAssemblyName(),
                TypeName = "RelationshipComboBoxMapper"
            };
            formField.UIControlMapperType = uiControlMapperType;
            UIControlType uiControlType = new UIControlType { AssemblyName = "System.Windows.Forms", TypeName = "ComboBox" };
            formField.UIControlType = uiControlType;

            //---------------Execute Test ----------------------
            ClassDefCol classDefs = new DmToClassDefsConverter().Convert((DMSolution) dmClass.Solution);
            IClassDef classDef = classDefs[dmClass.Assembly.AssemblyName, dmClass.ClassNameBO];
            //---------------Test Result -----------------------

            Assert.AreEqual(1, classDef.UIDefCol.Count);
            IUIDef uiDef = classDef.UIDefCol[view.ViewName];
            Assert.IsNotNull(uiDef.UIForm);
            IUIFormField field = uiDef.UIForm[0][0][0];
            Assert.AreEqual(relationship.RelationshipName, field.PropertyName);
            Assert.AreEqual(uiControlMapperType.AssemblyName, field.MapperAssembly);
            Assert.AreEqual(uiControlMapperType.TypeName, field.MapperTypeName);
            Assert.AreEqual(uiControlType.AssemblyName, field.ControlAssemblyName);
            Assert.AreEqual(uiControlType.TypeName, field.ControlTypeName);

            //---------------Tear Down -------------------------          
        }

        private static UIView AddViewToClass(DMClass dmClass)
        {
            UIView view = new UIView { ViewName = TestUtilsShared.GetRandomString() };
            dmClass.UIViews.Add(view);
            return view;
        }


        private UIField AddUIFormInfoToUIView(DMProperty property, UIView view)
        {
            UITab uiTab = new UITab();
            uiTab.Name = TestUtilsShared.GetRandomString();
            UIColumnLayout columnLayout = new UIColumnLayout();
            UIFormInfo formInfo = CreateUIFormInfo();
            UIField formField = new UIField();
            formField.Editable = false;
            formField.ShowAsCompulsory = false;
            formField.LabelText = TestUtilsShared.GetRandomString();
            formField.PropertyName = property.PropertyName;
            formField.ToolTipText = TestUtilsShared.GetRandomString();
            UIControlMapperType uiControlMapperType = new UIControlMapperType();
            uiControlMapperType.AssemblyName = TestUtilsShared.GetRandomString();
            uiControlMapperType.TypeName = TestUtilsShared.GetRandomString();
            formField.UIControlMapperType = uiControlMapperType;
            UIControlType uiControlType = new UIControlType();
            uiControlType.AssemblyName = TestUtilsShared.GetRandomString();
            uiControlType.TypeName = TestUtilsShared.GetRandomString();
            formField.UIControlType = uiControlType;
            columnLayout.UIFields.Add(formField);
            uiTab.UIColumnLayouts.Add(columnLayout);
            formInfo.UITabs.Add(uiTab);
            view.UIFormInfo = formInfo;
            return formField;
        }

        private UIFormInfo CreateUIFormInfo()
        {
            UIFormInfo formInfo = new UIFormInfo();
            formInfo.Height = TestUtilsShared.GetRandomInt();
            formInfo.Width = TestUtilsShared.GetRandomInt();
            formInfo.Title = TestUtilsShared.GetRandomString();
            return formInfo;
        }


        private static UIGridColumnInfo CreateUIGridColumnInfo(DMProperty property)
        {
            UIGridColumnInfo columnInfo = new UIGridColumnInfo { PropertyName = property.PropertyName, Heading = TestUtilsShared.GetRandomString() };
            return columnInfo;
        }

        private static UIGridInfo AddGridInfoToView(UIView view, DMProperty property)
        {
            UIGridInfo gridInfo = new UIGridInfo();
            view.UIGridInfo = gridInfo;
            gridInfo.SortColumn = property.PropertyName;
            UIGridColumnInfo columnInfo = new UIGridColumnInfo { PropertyName = property.PropertyName };
            gridInfo.UIColumns.Add(columnInfo);
            return gridInfo;
        }
    }
}
